#include "mcvdatum.h"
#include "mcvarray.h"

using namespace MCV;

Datum::Datum()
{
	_type = MCVUCHAR;
	_data.c = 0;
}

Datum::Datum(mcvuchar c) {
    _type = MCVUCHAR;
    _data.c = c;
}

Datum::Datum(mcvfloat d) {
    _type = MCVFLOAT;
    _data.d = d;
}

Datum::Datum(mcvint i) {
    _type = MCVINT;
    _data.i = i;
}

Datum::Datum(Array* ptr) {
    _type = MCVARRAY;
    _data.ptr = ptr;
	if(_data.ptr != NULL)
		_data.ptr->incrRefCount();
}

Datum::Datum(const Datum& orig) {
    _type = orig._type;
    _data = orig._data;
	if(_type == MCVARRAY && _data.ptr != NULL)
		_data.ptr->incrRefCount();
}

Datum::~Datum()
{
	if(_type == MCVARRAY && _data.ptr != NULL)
		_data.ptr->decrRefCount();
}

int Datum::type()
{
	return _type;
}

Datum::operator mcvint() {
    switch(_type) {
        case MCVUCHAR:
            return (mcvint)_data.c;
        case MCVFLOAT:
            return (mcvint)_data.d;
        case MCVINT:
            return _data.i;
        default:
            return 0;
    }
}

Datum::operator mcvfloat() {
    switch(_type) {
        case MCVUCHAR:
            return (mcvfloat)_data.c;
        case MCVFLOAT:
            return _data.d;
        case MCVINT:
            return (mcvfloat)_data.i;
        default:
            return 0;
    }
}

Datum::operator mcvuchar() {switch(_type) {
        case MCVUCHAR:
            return _data.c;
        case MCVFLOAT:
            return (mcvuchar)_data.d;
        case MCVINT:
            return (mcvuchar)_data.i;
        default:
            return 0;
    }
}

Datum::operator Array*() {
    switch(_type) {
        case MCVARRAY:
            return _data.ptr;
        default:
            return NULL;
    }
}

Datum& Datum::operator= (const mcvint& i)
{
	clear();
	_type = MCVINT;
	_data.i = i;
	return *this;
}

Datum& Datum::operator= (const mcvfloat& f)
{
	clear();
	_type = MCVFLOAT;
	_data.d = f;
	return *this;
}

Datum& Datum::operator= (const mcvuchar& u)
{
	clear();
	_type = MCVUCHAR;
	_data.c = u;
	return *this;
}

Datum& Datum::operator= (Array* ptr)
{
	clear();
	_type = MCVARRAY;
	_data.ptr = ptr;
	if(ptr)
		ptr->incrRefCount();
	return *this;
}

Datum& Datum::operator= (const Datum& rhs)
{
	clear();
	_type = rhs._type;
	_data = rhs._data;
	if(_type == MCVARRAY && _data.ptr != NULL)
		_data.ptr->incrRefCount();
	return *this;
}

void Datum::clear()
{
	if(_type == MCVARRAY && _data.ptr != NULL)
	{
		_data.ptr->decrRefCount();
		_data.ptr = NULL;
	}
}